/*******************************************************************************
* CSCI321 Major Project 2010 - University of Wollongong                        *
********************************************************************************
* Program:		WeaveEdit                                              *
* Authors:		Simon Allen (Student#: 3457527, Unix: sa655)           *
*			Scott Bellis (Student#: 3479110, Unix: sjb900)         *
*			Jason Benger (Student#: 3454137, Unix: jb960)          *
*			Timothy Newmarch (Student#: 3459263 Unix: tgn336)      *
*			Benjamin Richardson (Student# 3467752, Unix: bjr401)   *
* Supervisor:		Daniel F. Saffioti                                     *
* Modified:		28/10/2010                                             *
* Description:		WeaveEdit is a highly portable collaborative text      *
*			editor and word processor, allowing several users to   *
*			read and edit multiple documents at the same time.     *
*			It is available for Mac OS X, Windows and Linux,       *
*			utilising Nokia's Qt development framework.            *
*******************************************************************************/


#include <QSocketNotifier>
#include "bonjourresolver.h"
#include "bonjourbrowser.h"

BonjourBrowser::BonjourBrowser(QObject *parent) : QObject(parent)
{
		serviceRef = NULL;
}

BonjourBrowser::~BonjourBrowser()
{
	if (serviceRef)
		DNSServiceRefDeallocate(serviceRef);
}

void BonjourBrowser::startBrowsing(QString newType)
{
	if (serviceRef)
		return;

	type = newType;	//store the type

	//start browsing
	DNSServiceErrorType error;
	error = DNSServiceBrowse(&serviceRef, 0, 0, type.toAscii().constData(), NULL, browseCallback, this);

	if (error != kDNSServiceErr_NoError)
	{
		emit bonjourError();
		return;
	}

	//get the socket descriptor and wait for replies
	int sock = DNSServiceRefSockFD(serviceRef);

	if (sock == -1)
	{
		emit bonjourError();
		return;
	}

	//monitor the socket for new info
	QSocketNotifier *notify = new QSocketNotifier(sock, QSocketNotifier::Read, this);
	connect(notify, SIGNAL(activated(int)), this, SLOT(receiveSomeInfo(int)));
}

void BonjourBrowser::receiveSomeInfo(int)
{
	DNSServiceProcessResult(serviceRef);	//calls the callback
}


void BonjourBrowser::browseCallback(DNSServiceRef ref, DNSServiceFlags flags, quint32 index, DNSServiceErrorType error,
									const char *name, const char *type, const char *domain, void *context)
{
	//check if data will be valid
	if (error != kDNSServiceErr_NoError)
		return;

	//store the service data (we already know the type, so no need to store)
	BonjourService s;
	s.index = index;
	s.name = QString(name);
	s.domain = QString(domain);

	QList<BonjourService> *list = &(((BonjourBrowser*)context)->serviceList);

	if (flags & kDNSServiceFlagsAdd)
	{
	    bool alreadyInList = false;

	    for (int i = 0; i < list->length(); i++)
	    {
		if (s.name == list->at(i).name && s.domain == list->at(i).domain && s.index == list->at(i).index)
		{
		    alreadyInList = true;
		    break;
		}
	    }

	    if (!alreadyInList)
		list->append(s);
	}
	else
	{
		for (int i = 0; i < list->length(); i++)
		{
			if (s.name == list->at(i).name && s.domain == list->at(i).domain && s.index == list->at(i).index)
			{
				list->removeAt(i);
				break;
			}
		}
	}

	//if there are no more immediate callbacks coming, send a signal that changes have been made
	if (!(flags & kDNSServiceFlagsMoreComing))
		emit ((BonjourBrowser*)context)->serviceListUpdated(*list);
}

